package com.basaji.security;

import org.acegisecurity.Authentication;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.context.SecurityContext;
import org.acegisecurity.context.SecurityContextHolder;

import com.basaji.domain.pojo.Account;


/**
 * A wrapper of spring acegi security {@link SecurityContextHolder}.
 */
public final class UulogSecurityContext {

    private static final GrantedAuthority[] DEFAULT_GRANTED_AUTHORITIES =
            new GrantedAuthorityImpl[] {new GrantedAuthorityImpl("ROLE_USER") };

    /**
     * private constructor that prevents from instantiation.
     */
    private UulogSecurityContext() {
    }

    /**
     * Can only be invoked after a {@link SecurityContext} object has been
     * attached with current thread.
     * 
     * @return the current login user's {@link Account} object.
     */
    public static Account getCurrentAccount() {
        SecurityContext context = SecurityContextHolder.getContext();
        //Assert.notNull(context, "security context canot be null");
        PrincipalPasswordAuthenticationToken auth =
                (PrincipalPasswordAuthenticationToken) context.getAuthentication();
        if (auth == null) {
            return null;
        }
        
        return auth.getCurrentAccount();
    }
    
    public static void setCurrentAccount(Account account){
    	SecurityContext context = SecurityContextHolder.getContext();
        PrincipalPasswordAuthenticationToken auth =
                (PrincipalPasswordAuthenticationToken) context.getAuthentication();
        auth.setCurrentAccount(account);
        
    }

    /**
     * 
     * @param authResult
     *            the authentication object when the user login successfully.
     */
    public static void successfulAuthentication(Authentication authResult) {
        SecurityContextHolder.getContext().setAuthentication(authResult);
    }

    /**
     * 
     * @param requestToken
     *            the authentication object when the user login fails.
     */
    public static void unsuccessfulAuthentication(Authentication requestToken) {
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    /**
     * login the account in Hozom Server.
     * 
     * @param account
     *            user's account
     * @param token authentication token
     * 
     */
    public static void login(Account account, PrincipalPasswordAuthenticationToken token) {
        Authentication authResult = createSuccessAuthentication(account, token);
        successfulAuthentication(authResult);
    }

    /**
     * Create an
     * {@link PrincipalPasswordAuthenticationToken PrincipalPasswordAuthenticationToken}
     * when the user login successfully based on the given {@code account} and
     * {@code token}. <br />
     * Note we use {@link Account#getId() account id} as the return
     * authentication object's principal since the username and phone number of
     * the login account would be changed during its login time. <br />
     * And we use the {@link PrincipalPasswordAuthenticationToken token's}
     * credentials as the return object's credentials so that the user can be
     * re-authenticated if it is required (If the user change its password
     * during its login time).
     * 
     * @param account
     *            the login account.
     * @param token
     *            the {@link PrincipalPasswordAuthenticationToken} that the user
     *            request. The request contains the account's username and
     *            password.
     * @return a authentication token that with the account's ID as its
     *         principal, and the {@code token token's} credentials as its
     *         credentials.
     */
    public static Authentication createSuccessAuthentication(Account account,
                                                             PrincipalPasswordAuthenticationToken token) {
        return new PrincipalPasswordAuthenticationToken(DEFAULT_GRANTED_AUTHORITIES, account
                .getId(), token.getCredentials(), account, true);
    }

}
